package view.panels;

import java.awt.Color;
import java.awt.Dimension;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import util.resources.ResourceManager;
import controller.TurtleController;

/**
 * An abstract class which represents a standard list panel of type T as
 * implemented in our program.
 * 
 * @author Nathan Klug
 * 
 */
public abstract class AbstractListPanel<T>
{
    private static ResourceManager defaults = ResourceManager.getInstance();

    private JList myList;
    private DefaultListModel myListModel;
    private TurtleController myController;

    /**
     * Gets the width from the resource file by using reflection on the class
     * name
     * 
     * @return the width of the panel
     */
    private Dimension getDefaultSize()
    {
        String className = this.getClass().getName();
        return defaults.getDimension(className + "_size");
    }

    /**
     * Gets the name of the panel from the resource file by using reflection on
     * the class name
     * 
     * @return the name of the panel
     */
    protected String getListName()
    {
        String className = this.getClass().getName();
        return defaults.getString(className + "_name");
    }

    /**
     * Constructs the Abstract List Panel. This same constructor can be used for
     * most children.
     * 
     * @param controller
     */
    public AbstractListPanel(TurtleController controller)
    {
        this(controller, ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    }

    public AbstractListPanel(TurtleController controller, int selectionModel)
    {
        myController = controller;
        myListModel = new DefaultListModel();
        myList = new JList(myListModel);
        myList.setName(getListName());
        myList.setSelectionMode(selectionModel);
        myList.setLayoutOrientation(JList.VERTICAL);
        myList.setSize(getDefaultSize());
        myList.setBorder(BorderFactory.createLineBorder(Color.black));

        myList.addListSelectionListener(new ListSelectionListener()
        {
            public void valueChanged(ListSelectionEvent e)
            {
                eventOccurred(e);
            }
        });
    }

    public abstract void eventOccurred(ListSelectionEvent event);

    public void updateList(T newObject)
    {
        myListModel.add(myListModel.getSize(), newObject);
        myList.ensureIndexIsVisible(myListModel.getSize() - 1);
    }

    public void replaceList(List<T> newList)
    {
        myListModel.clear();
        for (T s : newList)
        {
            updateList(s);
        }
    }

    public JScrollPane getInstance()
    {
        JScrollPane panel = new JScrollPane(myList);
        return panel;
    }

    /**
     * Gets indices of all selected items
     * 
     * @return an array of integers whose elements are indices.
     */
    protected int[] getIndicesOfSelectedItems()
    {
        return myList.getSelectedIndices();
    }

    /**
     * Gets the index of the first item that is selected. If no items are
     * selected, -1 is returned
     * 
     * @return an integer, representing the index of the first item selected
     */
    protected int getIndexOfFirstSelectedItem()
    {
        return myList.getSelectedIndex();
    }

    /**
     * Gets an item from the list. This way, the list itself doesn't need to get
     * passed.
     * 
     * @param index
     *            the index of the item to get
     * @return the item at the given index
     */
    @SuppressWarnings("unchecked")
    protected T getListItem(int index)
    {
        return (T) myListModel.get(index);
    }

    /**
     * Children frequently need to call controller methods
     */
    protected TurtleController getController()
    {
        return myController;
    }

    /**
     * Used by child list who are only supposed to have one item selected at a
     * time.
     */
    protected void clearListSelection()
    {
        myList.clearSelection();
    }
}
